package checkers3d.logic;

import checkers3d.presentation.*;
import java.awt.Point;
import java.util.LinkedList;

/**
 *
 * @author      Sean Keel
 */
public class BoardObjectKing implements IBoardObjectDynamic {

    private Point drawPosition;
    private Player owner;
    private IRenderResource piecePicture;

    private final int SETUP_ROWS = 3;

    public BoardObjectKing(Player owner, IRenderResource icon)
    {
        setOwner(owner);
        setDrawPosition(new Point());
        setRenderResource(icon);
    }

    // Finds the path from selected piece to the target location and
    // returns a list of Point3Ds, or squares, that the piece must
    // move to or over in order to get to the new location.
    public LinkedList<Point3D> getPath(Point3D relativePosition) {
        LinkedList<Point3D> path = new LinkedList();

        // Single step up right: do not add any points
        if (relativePosition.x == 1 && relativePosition.y == 1);

        // Jump step up right: add first square diagonally in that direction
        else if (relativePosition.x == 2 && relativePosition.y == 2)
            path.add(new Point3D(1, 1, relativePosition.z));

        // Single step down right: do not add any points
        else if (relativePosition.x == 1 && relativePosition.y == -1);

        // Jump step down right: add first square diagonally in that direction
        else if (relativePosition.x == 2 && relativePosition.y == -2)
            path.add(new Point3D(1, -1, relativePosition.z));

        // Single step up left: do not add any points
        else if (relativePosition.x == -1 && relativePosition.y == 1);

        // Jump step up left: add first square diagonally in that direction
        else if (relativePosition.x == -2 && relativePosition.y == 2)
            path.add(new Point3D(-1, 1, relativePosition.z));

        // Single step down left: do not add any points
        else if (relativePosition.x == -1 && relativePosition.y == -1);

        // Jump step down left: add first square diagonally in that direction
        else if (relativePosition.x == -2 && relativePosition.y == -2)
            path.add(new Point3D(-1, -1, relativePosition.z));

        // Warp up: do not add any points
        else if (relativePosition.x == 0 && relativePosition.y == 0 && relativePosition.z == 1);

        // Warp down: do not add any points
        else if (relativePosition.x == 0 && relativePosition.y == 0 && relativePosition.z == -1);

        path.add(new Point3D(relativePosition.x,
            relativePosition.y, relativePosition.z));

        return path;
    }

    public boolean isBlocking() {
        return true;
    }

    // Returns true if a player has the right to select the piece
    public boolean isSelectableBy(Player player) {
        boolean flag;
        if (player == this.getOwner())
            flag = true;
        else
            flag = false;

        return flag;
    }

    public boolean isValidMoveTarget(PlayingSurface3D playingSurface, Point3D position, Point3D target) {

        if(!UtilBoardObject.isPositionBlocked(playingSurface.getPosition(target)))
        {
            // single step up left
            if (position.x-target.x == 1 && position.y-target.y == 1 && position.z==target.z)
                return true;
            // single step down left
            else if (position.x-target.x == 1 && position.y-target.y == -1 && position.z==target.z)
                return true;
            // single step up right
            else if (position.x-target.x == -1 && position.y-target.y == 1 && position.z==target.z)
                return true;
            // single step down right
            else if (position.x-target.x == -1 && position.y-target.y == -1 && position.z==target.z)
                return true;
        }
        return false;     
    }
    
    public boolean isValidWarpTarget(PlayingSurface3D playingSurface, Point3D position, Point3D target) {
        if(!UtilBoardObject.isPositionBlocked(playingSurface.getPosition(target)))
        {
            // warp up
            if (position.x-target.x == 0 && position.y-target.y == 0 && position.z-target.z == 1)
                return true;
            // warp down
            else if (position.x-target.x == 0 && position.y-target.y == 0 && position.z-target.z == -1)
                return true;
        }
        return false;
    }

    public boolean isValidJumpTarget(PlayingSurface3D playingSurface, Point3D position, Point3D target){

        if(!UtilBoardObject.isPositionBlocked(playingSurface.getPosition(target)))
        {
            // jump step up right
            if (position.x-target.x == 2 && position.y-target.y == 2 && position.z==target.z){
                Point3D midPoint = new Point3D(position.x-1,position.y-1,position.z);
                if(playingSurface.getPositionDynamicObject(midPoint)!=null && playingSurface.getPositionDynamicObject(position)!=null)
                    if(playingSurface.getPositionDynamicObject(midPoint).getOwner() != playingSurface.getPositionDynamicObject(position).getOwner())
                        return true;
            }
            // jump step down right
            else if (position.x-target.x == 2 && position.y-target.y == -2 && position.z==target.z){
                Point3D midPoint = new Point3D(position.x-1,position.y+1,position.z);
                if(playingSurface.getPositionDynamicObject(midPoint)!=null && playingSurface.getPositionDynamicObject(position)!=null)
                    if(playingSurface.getPositionDynamicObject(midPoint).getOwner() != playingSurface.getPositionDynamicObject(position).getOwner())
                        return true;
            }
            // jump step up left
            else if (position.x-target.x == -2 && position.y-target.y == 2 && position.z==target.z){
                Point3D midPoint = new Point3D(position.x+1,position.y-1,position.z);
                if(playingSurface.getPositionDynamicObject(midPoint)!=null && playingSurface.getPositionDynamicObject(position)!=null)
                    if(playingSurface.getPositionDynamicObject(midPoint).getOwner() != playingSurface.getPositionDynamicObject(position).getOwner())
                        return true;
            }
            // jump step down left
            else if (position.x-target.x == -2 && position.y-target.y == -2 && position.z==target.z){
                Point3D midPoint = new Point3D(position.x+1,position.y+1,position.z);
                if(playingSurface.getPositionDynamicObject(midPoint)!=null && playingSurface.getPositionDynamicObject(position)!=null)
                    if(playingSurface.getPositionDynamicObject(midPoint).getOwner() != playingSurface.getPositionDynamicObject(position).getOwner())
                        return true;
            }
        }
        return false;
    }

    public boolean isValidSetupPosition(PlayingSurface3D playingSurface3D, Point3D location) {
        boolean valid = false;

        if(!UtilBoardObject.isPositionBlocked(playingSurface3D.getPosition(location)))
            if(location.y >= (playingSurface3D.getSizeY() - SETUP_ROWS))
                valid = true;

        return valid;
    }

    // Returns true if this piece is visible to a certain player
    // Returns false otherwise.
    public boolean isVisibleTo(Object player) {
        return true;
    }

    // Sets owner of piece to be either home or visitor player
    public void setOwner(Player player) {
        owner = player;
    }

    // Retrieves image location of where this piece will be drawn
    public Point getDrawPosition() {
        return drawPosition;
    }

    // Sets the image location of where this piece will be drawn
    public void setDrawPosition(Point position) {
        drawPosition = position;
    }

    // Gets the image for this piece
    public IRenderResource getRenderResource() {
        return piecePicture;
    }

    // Sets the picture for this type of piece
    public void setRenderResource(IRenderResource resource) {
        this.piecePicture = resource;
    }

    // Gets the count setup
    public int getSetupCount(int boardSizeX, int boardSizeY, int boardSizeZ) {
        int setupCount = 1;
        
        return setupCount;
    }

    // Retrieves information about who owns the piece
    public Player getOwner() {
        return owner;
    }

    public BoardObjectTouchEffect onTouch(IBoardObject other) {
        if (getOwner() != other.getOwner() && (other instanceof BoardObjectChecker || other instanceof BoardObjectKing))
            return BoardObjectTouchEffect.REMOVE;
        else
            return BoardObjectTouchEffect.NOTHING;
    }

    /**
     * Returns a new instance of this object type with all local variables the
     * same.
     *
     * @return A new instance of this object.
     * @see IBoardObject
     */    
    @Override
    public IBoardObject clone()
    {
        return new BoardObjectKing(getOwner(), getRenderResource());
    }

    public String getDataAsString(){
        return ("King\t" + owner.getDataAsString());
    }

    @Override
    public String toString(){
        return (getClass().getName() + " - owner:" + getOwner());
    }
}
